home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / MacGofer 0.22d / MacGofer 0.22d Release / Gofer Documentation / Gofer Manual / ch10 < prev    next >
Text File  |  1991-12-30  |  20KB  |  238 lines

  1. ioneering  work  of  logicians
  2. including Church, Curry and Haskell, from whom the programming language
  3. takes its name.  The `\' character used at the  beginning  of  a  Gofer
  4. lambda expression has been chosen for  its  resemblance  to  the  greek
  5. letter lambda that might be used if the standard character set  were  a
  6. little larger.]
  7.  
  8. This expression denotes a function taking a number of  parameters  (one
  9. for each pattern) and producing the result specified by the  expression
  10. to the right of the -> symbol.  For example, (\x->x*x)  represents  the
  11. function which takes a single integer argument  `x'  and  produces  the
  12. square of that number as its result.  Another example is the the lambda
  13. expression (\x y->x+y) which takes two integer  arguments  and  outputs
  14. their sum; this expression is in fact equivalent to the (+) operator:
  15.  
  16.     ? (\x y->x+y) 2 3
  17.     5
  18.     (3 reductions, 7 cells)
  19.     ?
  20.  
  21. A lambda expression of the form illustrated above is equivalent to  the
  22. following expression using a local definition:
  23.  
  24.       (let newName <atomic patterns> = <expr> in newName)
  25.  
  26.  
  27.  
  28.                                       41
  29.  
  30.  
  31.  
  32.  
  33. Introduction to Gofer         10.3 Lambda expressions                           
  34.  
  35.  
  36. where "newName" is a new variable name, chosen to avoid conflicts  with
  37. other variables that are already in use.  This name will be printed  if
  38. you enter an expression involving a lambda expression without supplying
  39. the full number of parameters for that function:
  40.  
  41.     ? (\x y -> x+y) 42
  42.     v117 42
  43.     (2 reductions, 14 cells)
  44.     ?
  45.  
  46. Lambda expressions  are  particularly  useful  for  certain  styles  of
  47. functional programming; an example of this  is  the  continuation-based
  48. approach to I/O described in section 12.
  49.  
  50.  
  51. 10.4 Case expressions
  52. ---------------------
  53. A case expression can be used to evaluate an expression and,  depending
  54. on the result, return one of a number of  possible  values.   As  such,
  55. case statements are a  straightforward  generalisation  of  conditional
  56. expressions.  Indeed, an expression of the form "if e then t else f" is
  57. in fact equivalent to the case expression:
  58.  
  59.                         case e of 
  60.                           True  -> t
  61.                           False -> f
  62.  
  63. In general, a case expression takes the form "case exp of  alts"  where
  64. exp  is  the  expression  to  be  evaluated  and  alts  is  a  list  of
  65. alternatives, each of which is of the form:
  66.  
  67.         pat -> rhs                    for a simple alternative
  68.  
  69.     or: pat | condition1 -> rhs1      using guard expressions as
  70.             | condition2 -> rhs2      described in section 9.2 for
  71.                   .                   function definitions
  72.                   .
  73.             | conditionn -> rhsn
  74.  
  75. In Gofer, a case expression of the form case e of alts  is  implemented
  76. by choosing a new function name "newName" as in  the  previous  section
  77. and  using  the  alternatives  in  alts  to  construct  an  appropriate
  78. definition for this function (essentially by replacing each `->' symbol
  79. with a `=' symbol).  The complete case expression is  then  treated  as
  80. being equivalent to the expression "newName e".  A  simple  example  of
  81. this is the "scanl" function whose definition in the standard prelude:
  82.  
  83.     scanl f q xs = q : (case xs of
  84.                         []   -> []
  85.                         x:xs -> scanl f (f q x) xs)
  86.  
  87. is equivalent to:
  88.  
  89.     scanl f q xs = q : scanl' xs
  90.                    where scanl' []     = []
  91.                          scanl' (x:xs) = scanl f (f q x) xs
  92.  
  93.  
  94.                                       42
  95.  
  96.  
  97.  
  98.  
  99. Introduction to Gofer         10.4 Case expressions                             
  100.  
  101.  
  102. This latter form is precisely the definition used in [1] (but using the
  103. name "scan" where Gofer uses "scanl").
  104.  
  105. Evaluating a case expression in which none of  the  alternatives  match
  106. the value  of  the  discriminant  results  in  an  error  such  as  the
  107. following:
  108.  
  109.     ? case [1,2] of [] -> "empty list"
  110.     {v117 [1, 2]}
  111.     (6 reductions, 31 cells)
  112.     ?
  113.  
  114. The function name "v117" which appears here is the name of the function
  115. which is used internally by Gofer  to  implement  the  case  expression
  116. whilst the expression "[1, 2]" gives the discriminant value which could
  117. not be matched.
  118.  
  119. By combining case expressions with the lambda expressions introduced in
  120. the previous section, any function declaration can be translated into a
  121. single equation of the form <functionName> = <expr>.  For example,  the
  122. standard function "map" whose definition is usually written as:
  123.  
  124.     map f []     = []
  125.     map f (x:xs) = f x : map f xs
  126.  
  127. can also be defined by the equation:
  128.  
  129.     map = \f xs -> case xs of
  130.                      []     -> []
  131.                      (y:ys) -> f y : map f ys
  132.  
  133. This kind  of  translation  is  used  in  the  implementation  of  many
  134. functional programming languages, including Gofer.   See  Simon  Peyton
  135. Jones book [2] for more details of this.
  136.  
  137.  
  138. 10.5 Operator sections
  139. ----------------------
  140. As we have seen, most functions in Gofer taking more than one  argument
  141. are treated as a function of a  single  argument,  whose  result  is  a
  142. function which can then be applied to the  remaining  arguments.   Thus
  143. "(+) 1" denotes the function which takes an integer  argument  "n"  and
  144. returns the integer value "1+n".   Functions  of  this  kind  involving
  145. operator symbols are sufficiently common that Gofer provides a  special
  146. syntax for them.  Using e to denote an atomic expression and the symbol
  147. "*" to represent an arbitrary infix operator, there are functions (e *)
  148. and (* e), known as `sections of the operator (*)' defined by:
  149.  
  150.                   (e *) x  = e * x
  151.                   (* e) x  = x * e
  152.  
  153. or, using lambda expressions as introduced in section 10.3:
  154.  
  155.                   (e *)    =  \x -> e * x
  156.                   (* e)    =  \x -> x * e
  157.  
  158.  
  159.  
  160.                                       43
  161.  
  162.  
  163.  
  164.  
  165. Introduction to Gofer         10.5 Operator sections                            
  166.  
  167.  
  168. For example: (1+)   is the successor function which returns the value
  169.                     of its argument plus 1,
  170.              (1.0/) is the reciprocal function,
  171.              (/2)   is the halving function,
  172.              (:[])  is the function which maps any value to the
  173.                     singleton list containing that element.
  174.  
  175. In Gofer, the expressions "(e *)" and "(* e)" are actually  treated  as
  176. abbreviations for "(*) e" and "flip (*) e" respectively,  where  "flip"
  177. is the function defined by:
  178.  
  179.      flip        :: (a -> b -> c) -> b -> a -> c
  180.      flip  f x y  =  f y x
  181.  
  182. There is an important special case which occurs with an  expression  of
  183. the form (- e); this is interpreted  as  "negate  e"  and  not  as  the
  184. section which subtracts the value of "e" from its argument.  The latter
  185. function can be written as the section (+ (- e))  or  as  "subtract  e"
  186. where "subtract" is the function defined in the standard prelude using:
  187.  
  188.     subtract = flip (-)
  189.  
  190.  
  191. 10.6 Explicitly typed expressions
  192. ----------------------------------
  193. As described in section 9.12, it is often useful to be able to  declare
  194. the type of a variable defined in a function or pattern  binding.   For
  195. much the same reasons, Gofer allows expressions of the form:
  196.  
  197.                          <expr> :: <type>
  198.  
  199. so that the type of an expression can be  specified  explicitly.   Note
  200. that the :t command can be used  to  find  the  type  of  a  particular
  201. expression that is inferred by Gofer:
  202.  
  203.     ? :t  \x -> [x]
  204.     \x -> [x] :: a -> [a]
  205.  
  206.     ? :t  sum . map length
  207.     sum . map length :: [[a]] -> Int
  208.  
  209.     ? 
  210.  
  211. The types inferred in each case can be modified by  including  explicit
  212. types in these expressions:
  213.  
  214.     ? :t  (\x -> [x]) :: Char -> String
  215.     \x -> [x] :: Char -> String
  216.  
  217.     ? :t  sum . map (length :: String -> Int)
  218.     sum . map length :: [String] -> Int
  219.  
  220.     ?
  221.  
  222. Note that an error occurs if the type declared in an  explicitly  typed
  223. expression is not compatible with the type inferred by Gofer:
  224.  
  225.  
  226.                                       44
  227.  
  228.  
  229.  
  230.  
  231. Introduction to Gofer         10.6 Explicitly typed expressions                 
  232.  
  233.  
  234.     ? :t (\x -> [x]) :: Int -> a
  235.     ERROR: Declared type too general
  236.     *** Expression    : \x -> [x]
  237.     *** Declared type : Int -> a